﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using IteraProvisioning.Core;
using Microsoft.SharePoint.Client;
using OfficeDevPnP.Core.Entities;
using ProvisioningLibrary.Models;

namespace ProvisioningLibrary.Handlers
{
    public class WebHandler : ContentTypeHandler
    {
        private const string UsersGroup = "All in Itera";
        private const string OwnersGroup = "Itera Consulting Group Intranet Owners";
        private const string VisitorsGroup = "Itera Consulting Group Intranet Visitors";

        private ThemeEntity _theme;
        private List<AppInstance> _apps;
        private string _webUrl;

        public void ManageNewWeb(string urlSubsite, ContentType type, ThemeEntity theme, CustomerDetails details, List<AppInstance> apps)
        {
            _type = type;
            _theme = theme;
            _details = details;
            _apps = apps;
            _webUrl = urlSubsite;

            using (var context = GetContext(_webUrl))
            {
                ConfigureWeb(context);
            }
        }

        private void WebPartsHandling(ClientContext context)
        {
            // Apply content type and field values for custom app part to page
            AddContentType(context);

            // Insert app and client parts to page according to XML schema configuration
            WikiWebPartDefinition tasksListDef = new WikiWebPartDefinition()
            {
                WebPartIndex = 9,
                WebPartTitle = "Task list",
                WebPartZone = "wpz",
                WebPartXml = string.Format(Properties.Resources.ListView, CreateTaskList(context).Id, "Tasks list"),
                Row = 1,
                Column = 1,
                AddSpace = true,
                ToTop = false
            };
            context.Web.AddWebPartToWikiPage("sitepages", tasksListDef, "Home.aspx");

            WikiWebPartDefinition projectDetailsDef = new WikiWebPartDefinition()
            {
                WebPartIndex = 0,
                WebPartTitle = "CustomerDetailsAppPart", // Title should be the same as app title to add it to page
                WebPartZone = "wpz",
                WebPartXml = Properties.Resources.PageViewer,
                Row = 2,
                Column = 2,
                AddSpace = true,
                ToTop = true
            };
            AddCustomWebPart(context, projectDetailsDef);
        }

        private void AddCustomWebPart(ClientContext context, WikiWebPartDefinition webPartDef)
        {
            AppInstance app = _apps.Find(a => a.Title == webPartDef.WebPartTitle);
            if (app != null)
            {
                string appCurrentWebUrl = GetAppCurrentWebFullUrl(app.AppWebFullUrl, _webUrl, app.StartPage);
                webPartDef.WebPartXml = string.Format(webPartDef.WebPartXml, webPartDef.WebPartTitle, "300px", appCurrentWebUrl);
                context.Web.AddWebPartToWikiPage("sitepages", webPartDef, "Home.aspx");
            }
        }

        private string GetAppCurrentWebFullUrl(string appWebUrl, string hostUrl, string startPageUrl)
        {
            StringBuilder appFullUrl = new StringBuilder(startPageUrl);
            appFullUrl.Replace("~appWebUrl", appWebUrl);
            appFullUrl.Replace("{StandardTokens}", String.Empty);
            appFullUrl.AppendFormat("SPHostUrl={0}&amp;SPAppWebUrl={1}", HttpUtility.UrlEncode(hostUrl), HttpUtility.UrlEncode(appWebUrl));
            return appFullUrl.ToString();
        }

        private List CreateTaskList(ClientContext context)
        {
            List tasksList = context.Web.CreateList(ListTemplateType.TasksWithTimelineAndHierarchy, "Tasks List", false);
            context.Load(tasksList, tl => tl.Id);
            context.ExecuteQuery();
            return tasksList;
        }

        private void GroupHandling(ClientContext context)
        {
            string extContribGroup = String.Format("{0} External Contributors", _details.MaconomyId);
            if (!context.Web.GroupExists(extContribGroup))
            {
                Group contribGroup = context.Web.AddGroup(extContribGroup, "", true);
                context.Web.AddUserToGroup(contribGroup, UsersGroup);

                Group ppoGroup = context.Web.SiteGroups.GetByName(OwnersGroup);
                Group ppvGroup = context.Web.SiteGroups.GetByName(VisitorsGroup);
                context.Load(ppoGroup);
                context.Load(ppvGroup);
                context.ExecuteQuery();

                context.Web.AssociateDefaultGroups(ppoGroup, contribGroup, ppvGroup);
                context.Web.AddPermissionLevelToGroup(extContribGroup, RoleType.Contributor);
            }
        }

        private void ConfigureWeb(ClientContext context)
        {
            var newWeb = context.Web;
            // Set additional configuration properties
            newWeb.AllProperties["__InheritsThemedCssFolderUrl"] = "True";
            newWeb.BreakRoleInheritance(true, false);
            newWeb.Update();

            // Apply branding theme from site collection
            newWeb.SetComposedLookByUrl(String.Empty,
                UrlUtility.MakeRelativeUrl(_theme.Theme),
                UrlUtility.MakeRelativeUrl(_theme.Font),
                UrlUtility.MakeRelativeUrl(_theme.BackgroundImage),
                UrlUtility.MakeRelativeUrl(_theme.MasterPage));

            // Manage client web parts
            WebPartsHandling(context);
            // Manage custom group, users and permissions
            GroupHandling(context);
        }
    }
}